package Ms

import (
	"errors"
	"fmt"
	"db2s/ETL"
	"db2s/global"
	"strings"
)

type TableRows struct{}

/*
Sql sql server 生成查询数据的sql语句
*/
func (ms TableRows) Sql(s global.StartPart) (selectSql string, err error) {
	var (
		//event                                       = "[GeneratingQuerySql]"
		tableName                                   string
		selectColumn, whereCondition, orderByColumn []string
		tableSql                                    = TableSql{}
		hitIndexName                                string
	)
	var scnSql string

	//指定partition name会导致无法使用索引，进行全表扫描，且该sql为查询数据，已经通过索引列范围确定查询范围，所以不需要指定分区
	tableName = fmt.Sprintf(" %v.%v T %v where ", s.TableInfo.Schema, s.TableInfo.Table, scnSql)
	if !strings.EqualFold(s.TableInfo.PartitionName, "single") && len(s.TableInfo.PartitionName) > 0 {
		tableName = fmt.Sprintf(" %v.%v T where $PARTITION.%v %v and ", s.TableInfo.Schema, s.TableInfo.Table, s.TableInfo.PartitionName, scnSql)
	}
	if len(s.SelectColumn.IndexName) > 0 && !strings.EqualFold(s.TableInfo.PartitionName, "single") && len(s.TableInfo.PartitionName) > 0 {
		hitIndexName = fmt.Sprintf(" /*+ index(T %v) */ ", s.SelectColumn.IndexName)
	}
	//s.SelectColumn.OutputColumnType = "all"
	if selectColumn, _, err = tableSql.SelectColumn(s.SelectColumn); err != nil {
		return
	}
	if whereCondition, err = tableSql.WhereGenerate(s.WhereGenerate); err != nil {
		return
	}
	//if orderByColumn, err = tableSql.OrderBY(s.WhereGenerate); err != nil {
	//	return
	//}
	if len(orderByColumn) > 0 {
		selectSql = fmt.Sprintf("select %v %v from %v %s order by %s", hitIndexName, strings.Join(selectColumn, ","), tableName, strings.Join(whereCondition, " and "), strings.Join(orderByColumn, "\",\""))
	} else {
		selectSql = fmt.Sprintf("select %v from %v %s", strings.Join(selectColumn, ","), tableName, strings.Join(whereCondition, " and "))
	}
	return selectSql, nil
}

/*
Data Oracle 通过where条件查询表的分段数据（查询数据生成带有greatDbCheck标识的数据块）
*/
func (ms TableRows) Data(s global.RowsDataInput) (result global.ExecSqlResult, err error) {
	var (
		tableData   any
		event       = "[sqlserverData]"
		execTimeout int64
	)
	active := ETL.InstanceActiveS{DBType: DBType, DB: s.DB["single"], StopTime: s.Input.SqlExecStopTime, SqlMode: true}
	if s.Sql == "" || len(s.TableInfo.ShardName) == 0 || len(s.DB) == 0 {
		err = errors.New(fmt.Sprintf("%v sql exec fail. Execution process:{sql:%v,shard:%v,db:%v,err:%v}", event, s.Sql, s.TableInfo.ShardName, s.DB, err))
		return
	}
	if active.DB == nil {
		err = errors.New(fmt.Sprintf("%v sql exec fail. Execution process:{sql:%v,shard:%v,db:%v,err:%v}", event, s.Sql, s.TableInfo.ShardName, s.DB, err))
		return
	}

	if execTimeout, tableData, err = active.SqlQuery(s.Sql, ETL.GarthStringPointGarth); err != nil {
		err = errors.New(fmt.Sprintf("%v sql exec fail. Execution process:{sql:%v,shard:%v,db:%v,err:%v}", event, s.Sql, s.TableInfo.ShardName, s.DB, err))
		return
	}
	return global.ExecSqlResult{Timeout: execTimeout, Result: tableData}, nil
}

func (ms TableRows) MissData(s global.RowsDataInput) (result global.ExecSqlResult, err error) {
	var (
		event        = "[sqlServerMissData]"
		tableName    string
		selectColumn []string
		tableSql     = TableSql{}
		rowsLimit    string
	)
	var scnSql string
	if !strings.EqualFold(s.TableInfo.PartitionName, "single") {
		tableName = fmt.Sprintf(" %v.%v PARTITION(%v) %v ", s.TableInfo.Schema, s.TableInfo.Table, s.TableInfo.PartitionName, scnSql)
	} else {
		tableName = fmt.Sprintf(" %v.%v %v ", s.TableInfo.Schema, s.TableInfo.Table, scnSql)
	}
	s.SelectColumn.OutputColumnType = "all"
	if selectColumn, _, err = tableSql.SelectColumn(s.SelectColumn); err != nil {
		return
	}
	if s.TableInfo.RowsLimit > 0 {
		rowsLimit = fmt.Sprintf("TOP %v", s.TableInfo.RowsLimit)
	}
	if len(s.Input.TablePx) > 0 {
		result.ExecSql = fmt.Sprintf("select %v %v from %v OPTION (MAXDOP %v)", rowsLimit, strings.Join(selectColumn, ","), tableName, s.Input.TablePx)
	} else {
		result.ExecSql = fmt.Sprintf("select %v %v from %v", rowsLimit, strings.Join(selectColumn, ","), tableName)
	}
	active := ETL.InstanceActiveS{DBType: DBType, DB: s.DB["single"], StopTime: s.Input.SqlExecStopTime, FixRows: s.Input.FixRows, SqlMode: true}
	//var entry any
	if result.Timeout, result.Result, err = active.SqlQuery(result.ExecSql, ETL.FlowAny); err != nil {
		err = errors.New(fmt.Sprintf("%v sql exec fail. Execution process:{sql:%v,shard:%v,db:%v,err:%v}", event, result.ExecSql, "single", s.DB, err))
		return
	}
	return
}
